﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace Model
{
    /// <summary>
    /// 自定义map，用于键值对中值为大量数值且有排序要求的
    /// </summary>
    /// <typeparam name="T">Key</typeparam>
    /// <typeparam name="K">Value[链表]</typeparam>
    public class SortMultiMap<T, K>
    {
        private Dictionary<T, SortedSet<K>> dictionary = new Dictionary<T, SortedSet<K>>();
        // 重用list
        private Queue<SortedSet<K>> queue = new Queue<SortedSet<K>>();
        /// <summary>
        /// 获取值所在的字典
        /// </summary>
        /// <returns>value的字典</returns>
        public Dictionary<T, SortedSet<K>> GetDictionary()
        {
            return this.dictionary;
        }
        /// <summary>
        /// 添加指定的键值对
        /// </summary>
        /// <param name="t">key</param>
        /// <param name="k">value</param>
        public void Add(T t, K k)
        {
            SortedSet<K> list;
            this.dictionary.TryGetValue(t, out list);
            if (list == null)
            {
                list = this.FetchList();
                this.dictionary[t] = list;
            }
            list.Add(k);
        }
        /// <summary>
        /// 返回键值对的第一组
        /// </summary>
        /// <returns></returns>
        public KeyValuePair<T, SortedSet<K>> First()
        {
            return this.dictionary.First();
        }
        /// <summary>
        /// 返回键值对的数量
        /// </summary>
        public int Count
        {
            get
            {
                return this.dictionary.Count;
            }
        }
        /// <summary>
        /// 获取K类型的List(再生)
        /// </summary>
        /// <returns></returns>
        private SortedSet<K> FetchList()
        {
            if (this.queue.Count > 0)
            {
                SortedSet<K> list = this.queue.Dequeue();
                list.Clear();
                return list;
            }
            return new SortedSet<K>();
        }
        /// <summary>
        /// 将K类型链表加入再生队列中
        /// </summary>
        /// <param name="list"></param>
        private void RecycleList(SortedSet<K> list)
        {
            // 防止暴涨
            if (this.queue.Count > 50)
            {
                return;
            }
            list.Clear();
            this.queue.Enqueue(list);
        }
        /// <summary>
        /// 移除指定键值对的值队列中的一个K
        /// </summary>
        /// <param name="t">key</param>
        /// <param name="k">要移除的K</param>
        /// <returns>成功返回true</returns>
        public bool Remove(T t, K k)
        {
            SortedSet<K> list;
            this.dictionary.TryGetValue(t, out list);
            if (list == null)
            {
                return false;
            }
            if (!list.Remove(k))
            {
                return false;
            }
            if (list.Count == 0)
            {
                this.RecycleList(list);
                this.dictionary.Remove(t);
            }
            return true;
        }
        /// <summary>
        /// 移除指定键值对
        /// </summary>
        /// <param name="t">key</param>
        /// <returns>成功返回true</returns>
        public bool Remove(T t)
        {
            SortedSet<K> list = null;
            this.dictionary.TryGetValue(t, out list);
            if (list != null)
            {
                this.RecycleList(list);
            }
            return this.dictionary.Remove(t);
        }
        /// <summary>
        /// 移除所有键值对中值链表中的K
        /// </summary>
        /// <param name="k">要移除的k</param>
        /// <returns></returns>
        public bool Remove(Predicate<K> m)
        {
            foreach (SortedSet<K> t in dictionary.Values)
            {
                t.RemoveWhere(m);
            }
            return true;
        }
        /// <summary>
        /// 不返回内部的list,以数组形式copy一份出来
        /// </summary>
        /// <param name="t">key</param>
        /// <returns></returns>
        public K[] GetAll(T t)
        {
            SortedSet<K> list;
            this.dictionary.TryGetValue(t, out list);
            if (list == null)
            {
                return new K[0];
            }
            return list.ToArray();
        }
        /// <summary>
        /// 返回内部的list
        /// </summary>
        /// <param name="t">key</param>
        /// <returns></returns>
        public SortedSet<K> this[T t]
        {
            get
            {
                SortedSet<K> list;
                this.dictionary.TryGetValue(t, out list);
                return list;
            }
        }
        /// <summary>
        /// key下值链表中是否含有k
        /// </summary>
        /// <param name="t">key</param>
        /// <param name="k">value</param>
        /// <returns></returns>
        public bool Contains(T t, K k)
        {
            SortedSet<K> list;
            this.dictionary.TryGetValue(t, out list);
            if (list == null)
            {
                return false;
            }
            return list.Contains(k);
        }
        /// <summary>
        /// 表中是否有t
        /// </summary>
        /// <param name="t">key</param>
        /// <returns></returns>
        public bool ContainsKey(T t)
        {
            return this.dictionary.ContainsKey(t);
        }

        public void Clear()
        {
            foreach (KeyValuePair<T, SortedSet<K>> keyValuePair in this.dictionary)
            {
                this.RecycleList(keyValuePair.Value);
            }
            this.dictionary.Clear();
        }
    }
}